package me.flyray.crm.core.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class EncryptComp {

	private static final String Algorithm = "DESede";
	private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	/**
	 * encode string
	 * 
	 * @param algorithm
	 * @param str
	 * @return String
	 */
	public static String encode(String algorithm, String str) {
		if (str == null) {
			return null;
		}
		try {
			MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
			messageDigest.update(str.getBytes());
			return getFormattedText(messageDigest.digest());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	/**
	 * encode By MD5
	 * 
	 * @param str
	 * @return String
	 */
	public static String encodeByMD5(String str) {
		return encode("MD5",str);

	}
	
	public static String encodeBySHA1(String str){
		return encode("SHA1",str);
	}
	
	public static String encodeBy3DES(String key, String src) {
		try {
			byte[] keybyte = build3DesKey(key);
			SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
			Cipher c1 = Cipher.getInstance(Algorithm);
			c1.init(Cipher.ENCRYPT_MODE, deskey);
			return byte2Hex(c1.doFinal(src.getBytes("UTF-8")));
		} catch (java.security.NoSuchAlgorithmException e1) {
			throw new RuntimeException(e1);
		} catch (javax.crypto.NoSuchPaddingException e2) {
			throw new RuntimeException(e2);
		} catch (java.lang.Exception e3) {
			throw new RuntimeException(e3);
		}
	}
	
	public static byte[] encodeBy3DES(String key, byte[] src) {
		try {
			byte[] keybyte = build3DesKey(key);
			SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
			Cipher c1 = Cipher.getInstance(Algorithm);
			c1.init(Cipher.ENCRYPT_MODE, deskey);
			return c1.doFinal(src);
		} catch (java.security.NoSuchAlgorithmException e1) {
			throw new RuntimeException(e1);
		} catch (javax.crypto.NoSuchPaddingException e2) {
			throw new RuntimeException(e2);
		} catch (java.lang.Exception e3) {
			throw new RuntimeException(e3);
		}
	}

	public static String decodeBy3DES(String key, String src) {
		try {
			byte[] keybyte = build3DesKey(key);
			SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
			Cipher c1 = Cipher.getInstance(Algorithm);
			c1.init(Cipher.DECRYPT_MODE, deskey);
			return new String(c1.doFinal(hex2Byte(src)),"UTF-8");
		} catch (java.security.NoSuchAlgorithmException e1) {
			throw new RuntimeException(e1);
		} catch (javax.crypto.NoSuchPaddingException e2) {
			throw new RuntimeException(e2);
		} catch (java.lang.Exception e3) {
			throw new RuntimeException(e3);
		}
	}
	
	public static byte[] decodeBy3DES(String key, byte[] src) {
		try {
			byte[] keybyte = build3DesKey(key);
			SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
			Cipher c1 = Cipher.getInstance(Algorithm);
			c1.init(Cipher.DECRYPT_MODE, deskey);
			return c1.doFinal(src);
		} catch (java.security.NoSuchAlgorithmException e1) {
			throw new RuntimeException(e1);
		} catch (javax.crypto.NoSuchPaddingException e2) {
			throw new RuntimeException(e2);
		} catch (java.lang.Exception e3) {
			throw new RuntimeException(e3);
		}
	}
	
	private static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException{
		byte[] key = new byte[24];
        byte[] temp = keyStr.getBytes("UTF-8");
        if(key.length > temp.length){
            //如果temp不够24位，则拷贝temp数组整个长度的内容到key数组中
            System.arraycopy(temp, 0, key, 0, temp.length);
        }else{
            //如果temp大于24位，则拷贝temp数组24个长度的内容到key数组中
            System.arraycopy(temp, 0, key, 0, key.length);
        }
        return key;
	}
	
	private static String byte2Hex(byte[] b) {
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1) {
				hs = hs + "0" + stmp;
			} else {
				hs = hs + stmp;
			}
		}
		return hs.toUpperCase();
	}
	
	private static byte[] hex2Byte(String str) {
		if (str == null)
			return null;
		str = str.trim();
		int len = str.length();
		if (len == 0 || len % 2 == 1)
			return null;
		byte[] b = new byte[len / 2];
		try {
			for (int i = 0; i < str.length(); i += 2) {
				b[i / 2] = (byte) Integer.decode("0x" + str.substring(i, i + 2)).intValue();
			}
			return b;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Takes the raw bytes from the digest and formats them correct.
	 * 
	 * @param bytes
	 *            the raw bytes from the digest.
	 * @return the formatted bytes.
	 */
	private static String getFormattedText(byte[] bytes) {
		int len = bytes.length;
		StringBuilder buf = new StringBuilder(bytes.length * 2);
		// 把密文转换成十六进制的字符串形式
		for (int j = 0; j < len; j++) {
			buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
			buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
		}
		return buf.toString();
	}
	
	/**
	 * 生成随机字符串
	 * @author Dzxing
	 * @2016年12月16日 下午7:41:24
	 * @param length 字符串长度
	 * @return
	 */
    public static String genRandomStr(int length) {  
        String val = "";  
        Random random = new Random();  
          
        //参数length，表示生成几位随机数  
        for(int i = 0; i < length; i++) {  
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";  
            //输出字母还是数字  
            if( "char".equalsIgnoreCase(charOrNum) ) {  
                //输出是大写字母还是小写字母  
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;  
                val += (char)(random.nextInt(26) + temp);  
            } else if( "num".equalsIgnoreCase(charOrNum) ) {
                val += String.valueOf(random.nextInt(10));
            }  
        }  
        return val;  
    }  
    
    public static String encrypt(String str){
        String random = genRandomStr(8);
        str = random.substring(0, 3) + str + random.substring(3, 8);
        return encode("SHA1",str);
    }
    
    public static String encrypt(String str, String random){
        str = random.substring(0, 3) + str + random.substring(3, 8);
        return encode("SHA1",str);
    }

	public static void main(String[] args) {
		System.out.println("111111 MD5  :" + EncryptComp.encodeByMD5("111111"));
		System.out.println("111111 MD5  :"+ EncryptComp.encode("MD5", "111111"));
		System.out.println("111111 SHA1 :"+ EncryptComp.encode("SHA1", "111111"));
	}

}
